/* Copied from the source of the Wiki page:
 * http://oeis.org/wiki/User:Anatoly_E._Voevudko/VoeLib.gp
 * Reformatted using cleanwsf() from VoeLib.gp library. 
 * With testing samples.
 * 03/23/2016
 */

\\*== General Purpose PARI Scripts Library (presentation, lists/vectors handling, testing, calculating metrics, handling strings) ==

\\*'''Notes for those who are new to MediaWiki pages:'''
\\** Everyone is allowed to view and copy source.
\\** To copy or save a page without HTML tags click "view source" tab (at the top of this Wiki page).
\\** Then select all code inside Wiki page sub-window with source (depends on browser and OS), "Copy" it and save.
\\** Clean-up rules: delete all rows having at position 1 not a whitespace.
\\** You may add "\\" in front of such rows instead of deleting. Or you can use cleanwsf() & clean4gpf() from VoeLib.gp to do this hard job for you. Note: cleanwsf() & clean4gpf() works fine only here (with my style of formatting).

\\*=== Generic Functions (presentation, lists/vectors handling) ===

/* Author: Anatoly E. Voevudko 
 * Library of small functions useful for text presentation of numbers, working 
 * with lists/vectors, testing, calculating metrics and handling strings.
 * This PARI/GP library of scripts is a free software, covered by the GNU 
 * General Public License, and comes WITHOUT ANY WARRANTY WHATSOEVER.
 * NOTE: 1. Functions #2-#10 work with lists only/mostly. List items are mostly
 *          positive integers.
 *          If you need vector, then convert vector to list (simple assignment),
 *          apply function, and convert result (if it is a list) back to vector.
 *       2. Functions #2.1 - #2.5 were tested only for Win XP, but OK for any Windows. 
 *       3. Functions #3.1 - #3.9 calculate the most popular metrics applied 
 *          to equations like a+b=c, including A^x+B^y=C^z. They are used
 *          for definition of conjectures, estimation, selection etc.
 *       4. Functions #4.1 - #4.15 represent the set of basic string functions. 
 *          This is a very basic set of string functions, - just for presentation purposes,
 *          not for heavy text processing.
 *          Note: 1. Results can vary from results of similarly looking string functions 
 *          ====     you are using in C/C++, VB, Perl, PHP, etc.
 *                2. Some functions are using another functions from this set.
 *                   So, load the whole set.
 *       5. Functions working with files are using Windows conventions. Update them or
 *          delete them together with testing samples.
 * Updates: 9/11/2015 - 03/14/2016
 */
addhelp(VoeLib, "VoeLib.gp: Library of small functions useful for text presentation of numbers, working with lists/vectors, testing, calculating metrics and handling strings.");
\\* #1 Last updated: 9/11/2015
addhelp(factintxt, "factintxt(n): Factors of n in the text form.");
factintxt(n)=
{my(F=factor(n), m="", fit="", pend="", fn);
  if(n==1, return("1")); 
  fn=#F[,1];
  for(i=1, fn, if(i>1,m="*"); pend=""; if(F[i,2]>1, pend=Str("^", F[i,2]));
      fit = Str(fit, m, F[i,1],pend));
  return(fit);
}
   
\\* #2 - #3 Last updated: 9/11/2015
addhelp(findinlist, "findinlist(list,item,sind=1): Find the first item in any list starting with sind index (return 0 or index).");
findinlist(list, item, sind=1)=
{my(idx=0, ln=#list);
  if(ln==0 || sind<1 || sind>ln, return(0)); 
  for(i=sind, ln, if(list[i]==item, idx=i; break;)); 
  return(idx);
}
addhelp(findinlista, "findinlista(list,item,sind=1): Find all items in any list starting with sind index (return List() or List([ind1, ind2,...])).");
findinlista(list, item, sind=1)=
{my(ln=#list, Li=List());
  if(ln==0 || sind<1 || sind>ln, return(Li)); 
  for(i=sind, ln, if(list[i]==item, listput(Li,i))); 
  return(Li);
}

\\* #4 - #5 Last updated: 9/17/2015
\\* NOTE: Error token et must be < min(list[i]) to avoid confusion.
\\* ====  E.g., -1 for positive integers.
\\*       Usually, et means bad parameters (also known as the list of formal 
\\*       variables or arguments) in function call, so nothing done yet.
addhelp(listmax, "listmax(list, sind=1, et=-1): Return max number in the list of integers starting with sind index.");
listmax(list, sind=1, et=-1)= 
{my(ln=#list, li, mn);
   if(ln==0 || sind<1 || sind>ln, return(et)); 
   mn=list[sind];
   for(i=sind+1, ln, li=list[i]; if(li>mn, mn=li););
   return(mn);
}
addhelp(listmin, "listmin(list, sind=1, et=-1): Return min number in the list of integers starting with sind index.");
listmin(list, sind=1, et=-1)= 
{my(ln=#list, li, mn);
   if(ln==0 || sind<1 || sind>ln, return(et));
   mn=list[sind];
   for(i=sind+1, ln, li=list[i]; if(li<mn, mn=li););
   return(mn);
}

\\* #6 Last updated: 9/21/2015
\\* NOTE: Returns error token et: -1,0,ind>0 
\\*       (bad parameters/identical/NOT identical @ind). 
addhelp(volcomp, "volcomp(v1,v2): Vectors or lists compare, i.e., compare 2 vectors v1 and v2 (or 2 lists, or vector & list).");
volcomp(v1,v2)=
   {my(v1n=#v1,v2n=#v2,vmn=min(v1n,v2n),ip,cr=1,et=0);
   if(v1n<1||v2n<1, return(-1)); \\ wrong size(s)
   print(" *** COMPARE v1&v2 w/types: ",type(v1),"/",type(v2),"; w/sizes: ",v1n,"/",v2n);
   if(v1n!=v2n, print(" *** can compare only first ",vmn," elements."));
   for(i=1, vmn, if(v1[i]!=v2[i], ip=i; et=ip; cr=0; break));
   if(cr, print(" *** v1 and v2 are identical!"),
          print(" *** v1 and v2 are NOT identical at v1[",ip,"]!?"));
   return(et);
}

\\* #7 Last updated: 9/26/2015
\\* This is to help sorting text lists, and other non numeric objects in the list,
\\* which are related to (unsorted) input list.
\\* Note: If an input list has multiple equal items, then first of all convert it 
\\*       using listwui(list).
addhelp(sortlstgind, "sortlstgind(list): Sort an input list of integers and get list of indices in the input list (a.k.a. inderect sorting).");
sortlstgind(list)=
{my(Ls=List(),Li=List(), j, lsn=#list);
if(lsn==0, return(Ls));
Ls=list; listsort(Ls); 
for(i=1, lsn, j=findinlist(list, Ls[i]); listput(Li, j)); 
return(Li);
} 
 
\\* #8 Last updated: 9/27/2015
\\* This is to sort text lists, and other non numeric objects in the list.
addhelp(sortlstbyind, "sortlstbyind(inlist,indlist): Sort any input list using list of indices, and return sorted list. Both lists MUST have equal sizes.");
sortlstbyind(inlist,indlist)=
{my(Ls=List(), in=#inlist, iln=#indlist);
if(in==0 || iln==0 || in<>iln, print("*** Error: list sizes are not equal!"); return(Ls));
for(i=1, iln, listput(Ls, inlist[indlist[i]])); 
return(Ls);
} 

\\* #9 Last updated: 10/3/2015
addhelp(topp10, "topp10(n): Top power of 10 (tp) that is covering integer n (in other words 10^tp > n).");
topp10(n) = {my(sn,tp); if(n==0, return(0)); sn=Str(n); tp=10^#sn; return(tp);}

\\* #10 Last updated: 10/4/2015
addhelp(listwui, "listwui(list): Return reformatted input list of integers with all unique items.");
listwui(list)=
{my(Lu=List(),Li=Lu, lmn,tp, ii,im, ln=#list,lin);
 if(ln==0, return(Lu));
 lmn=listmax(list); tp=topp10(lmn);
 for(i=1, ln, listput(Lu, list[i]*tp));
 for(i=1, ln, ii=Lu[i];
   Li=findinlista(Lu, ii); lin=#Li;
   if(lin==0, next); if(lin==1, next); 
   for(j=1, lin, im=Li[j]; Lu[im]=Lu[im]+j);
 );
 return(Lu);
}

\\* #11 - #12 Last updated: 10/20/2015
addhelp(fmis, "fmis(mis): Return reformatted mis milliseconds.");
fmis(mis)=
{my(sec,ms,mn,sc,res);
 sec=floor(mis/1000); ms=mis-sec*1000; mn=floor(sec/60); sc=sec-mn*60;
 res = concat([mn,"min ", sc, "sec ", ms,"ms"]); return(res);  
}
addhelp(gettf, "gettf(pf=0): Return reformatted gettime() result. Print if pf=1.");
gettf(pf=0)=
{my(gt,res); gt=gettime(); res=fmis(gt); if(pf==1, print(res)); return(res);}

\\*=== Operating System Dependent Functions (for testing mostly) ===

\\* #2.1 - #2.5 Last updated: 9/27/2015
\\*  NOTE: Thes functions were tested only for Win XP, but OK for any Windows (according
\\*  ====  to Microsoft). So, delete them if you have a different OS.
\\*        Also, you can adopt them to your OS, if you need them for scripting.
\\*        Additionally, fpathname MUST be using "\\" like in the following sample: 
\\*        "c:\\pariData\\testfile1.txt".
\\*  #2.1 delfile  
addhelp(delfile, "delfile(fpathname): Delete fpathname file that already exists (Windows).");
delfile(fpathname)={my(cmd="del "); cmd=concat([cmd,fpathname]); system(cmd);}
\\*  #2.2 renfile 
addhelp(renfile, "renfile(fpathname,fnewname): Rename fpathname file that already exists (Windows).");
renfile(fpathname,fnewname)={my(cmd="ren "); cmd=concat([cmd,fpathname," ",fnewname]); system(cmd);}
\\*  #2.3 currdate  
addhelp(currdate, "currdate(): Print current system date (Windows).");
currdate()={system("date /t");}
\\*  #2.4 currtime 
addhelp(currtime, "currtime(): Print current system time (Windows).");
currtime()={system("time /t");}
\\*  #2.5 shutdown
\\*  NOTE: This one is useful if you are leaving your script to run overnight.
addhelp(shutdown, "shutdown(sec=20): Shut down your computer after sec seconds (Windows).");
shutdown(sec=20)={my(cmd="shutdown -s -f -t "); cmd=concat([cmd,sec]); system(cmd);}

\\*=== Functions Calculating Popular Equation Metrics ===

\\* NOTE: The following set of functions #3.1 - #3.9 contains all the most popular
\\* ****  metrics calculated and applied to equations like a+b=c, including A^x+B^y=C^z.
\\*       They are used for definition of conjectures, estimation, selection etc.
\\* #3.1 - #3.9 Last updated: 11/11/2015
\\* #3.1 sizec 
addhelp(sizec, "sizec(a,b): Size c in a sum a+b=c.");
sizec(a,b)={my(c=a+b); return(#Str(c));}
\\* #3.2 srecip
addhelp(srecip, "srecip(x,y,z): Sum of x,y,z reciprocals: 1/x+1/y+1/z.");
srecip(x,y,z)={return(1./x+1/y+1/z);}
\\* #3.3 rad
addhelp(rad, "rad(n): Radical of n (product of the distinct prime factors of n).");
rad(n)=
{my(F=factor(n),fn);
  if(n==1, return(1)); 
  fn=#F[,1]; return(prod(i=1,fn,F[i,1]));
}
\\* #3.4 merit
addhelp(merit, "merit(a,b): Merit of a sum a+b=c.");
merit(a,b)=
{my(c=a+b,lr=log(rad(a*b*c)),m);
 m=(qual(a,b)-1)^2*lr*log(lr);
 return(m);
}
\\* #3.5 qual
addhelp(qual, "qual(a,b): Quality (a.k.a. Power) of a sum a+b=c.");
qual(a,b)=
{my(c=a+b,h=log(c));
 return(h/log(rad(a*b*c)));
}
\\* #3.6 gqual
addhelp(gqual, "gqual(a,b): Granville quality of a sum a+b=c.");
gqual(a,b)=
{my(c=a+b,p=a*b*c,gq);
 gq=(qual(a,b)-1)*log(rad(p))/bigomega(p);
 return(gq);
}
\\* #3.7 squal
addhelp(squal, "squal(a,b): Szpiro quality of a sum a+b=c.");
squal(a,b)=
{my(c=a+b,p=a*b*c,h=log(p));
 return(h/rad(p));
}
\\* #3.8 gsqual
addhelp(gsqual, "gsqual(a,b): Granville-Szpiro quality of a sum a+b=c.");
gsqual(a,b)=
{my(c=a+b,p=a*b*c,gsq);
 gsq=(squal(a,b)-3)*rad(p)/bigomega(p);
 return(gsq);
}
\\* #3.9 popmetrics
addhelp(popmetrics, "popmetrics(a,b): Popular metrics of a sum a+b=c in 1 string: gcd, size, rad, merit, qual");
popmetrics(a,b)=
{my(c=a+b,gc,sz,sr,r,mr,q,pm);
 gc=gcd(a,b);
 sz=sizec(a,b);
 r=rad(a*b*c);
 mr=merit(a,b);
 q=qual(a,b);
 pm=Strprintf("*%d*|sz%d|r%d|mr%.2f|q%.4f",gc,sz,r,mr,q);
 return(pm);
}
   
\\*=== Basic string functions ===

\\* #4.1 - #4.12 *** Basic string functions ***
\\* This is a very basic set of string functions, - just for presentation purposes,
\\* not for heavy text processing.

\\* #4.1 - #4.2 schr(), sasc() 3/1/16
addhelp(schr, "schr(): Returns a one-character string containing the character specified by ASCII code ascii.");
schr(ascii)={return(Strchr(ascii))}
addhelp(sasc, "sasc(str): Returns the ASCII code of the first character of the str string.");
sasc(str)={my(vt=Vecsmall(str),sn=#str); if(sn>0, return(vt[1]), return(-1))}
   
\\* #4.3 srepeat() 3/3/16
addhelp(srepeat, "srepeat(str,ntimes): Repeat a string str the specified number of times ntimes and return composed string.");
srepeat(str,ntimes)={
my(srez=str,nt=ntimes-1);
if(ntimes<1||#str==0,return("")); 
if(ntimes==1,return(str)); 
for(i=1,nt, srez=concat(srez,str));
return(srez);
}
\\* #4.4 sreverse() 3/3/16
addhelp(sreverse, "sreverse(str): Return reversed string str.");
sreverse(str)={return(Strchr(Vecrev(Vecsmall(str))))}
\\* #4.5  spad() 3/3/16
addhelp(spad, "spad(str,newsize,padchr=\" \",sflag=2): Returns the input string str padded on the right or left to the specified length newsize using character padchr. Side flag sflag = 1/2 (left/right).");
spad(str,newsize,padchr=" ",sflag=2)={
my(sn=#str,pn=newsize-sn,p,sr=srepeat(padchr,pn));
if(newsize<=sn,return(str));
if(sflag<1||sflag>2,sflag=2);
if(sflag==2,p=concat(str,sr),p=concat(sr,str));
return(p);
}
   
\\* #4.6 ssubstr() 3/5/16
addhelp(ssubstr, "ssubstr(str,s=1,n=0): Returns the substring of string str specified by the start position s and length n. If n=0 then to the end of str.");
ssubstr(str,s=1,n=0)={
my(vt=Vecsmall(str),ve,vr,vtn=#str,n1);
if(vtn==0,return(""));
if(s<1||s>vtn,return(str));
n1=vtn-s+1; if(n==0,n=n1); if(n>n1,n=n1);
ve=vector(n,z,z-1+s); vr=vecextract(vt,ve); return(Strchr(vr));
}
\\* #4.7 sfind1s() 3/5/16
\\ Upgraded contains() script from http://rosettacode.org/wiki/String_matching#PARI.2FGP
addhelp(sfind1s, "sfind1s(str,substr,s): Within string str find first substring substr beginning the start position s.. Return position or 0 if not found.");
sfind1s(str,substr,s=1)={
my(vs=Vecsmall(str),vss=Vecsmall(substr),sn=#str,ssn=#substr,dn=sn-ssn,is=s-1,ok);
if(s<1||s>sn,return(0)); if(ssn>sn,return(0));
for(i=is,dn, ok=1; for(j=1,ssn, if(vs[i+j]!=vss[j], ok=0; break)); 
    if(ok, return(i+1))
);\\fend i
}
\\* #4.8 sfindalls() 3/5/16
addhelp(sfindalls, "sfindalls(str,substr): Within string str find all substrings substr. Return all found positions in vector or empty vector if found none.");
sfindalls(str,substr)={
my(sn=#str,ssn=#substr,dn=sn-ssn,is=1,L=List());
if(ssn>sn,return([]));
if(dn==0,dn=1);
for(i=1,dn, is=sfind1s(str,substr,is);
    if(is!=0, listput(L,is); is++; next, break);
);\\fend i
return(Vec(L));    
}
\\* #4.9 stok() 3/5/16
\\* Delimiter is allowed in any place. In addition, multiple delimiters are allowed too.
\\* This is really useful for considering omitted data. 
\\* This version can be used for positional parameters processing, or for processing data from tables with string rows.
addhelp(stok, "stok(str,d): Tokenize a string str according to 1 character delimiter d. Return a vector of tokens.");
stok(str,d)={
my(d1c=ssubstr(d,1,1),str=Str(str,d1c),vt=Vecsmall(str),d1=sasc(d1c),
   Lr=List(),sn=#str,v1,p1=1,vo=32);
if(sn==1, return([""])); if(vt[sn-1]==d1,sn--);
for(i=1,sn, v1=vt[i];
    if(v1!=d1, vo=v1; next);
    if(vo==d1||i==1, listput(Lr,""); p1=i+1; vo=v1; next);
    if(i-p1>1, listput(Lr,ssubstr(str,p1,i-p1)); p1=i+1);
    vo=v1;
   ); 
return(Vec(Lr));
}
   
\\* #4.10 sstripchars() 3/6/16
\\* Upgraded from the script in:
\\* http://rosettacode.org/wiki/Strip_a_set_of_characters_from_a_string#PARI.2FGP
addhelp(sstripchars, "sstripchars(str,chrs): From str string strip a set of characters given in the string chrs and return result.");
sstripchars(str,chrs)={
my(vs=Vecsmall(str),vc=Set(Vec(Vecsmall(chrs))),v=[],vsn=#str,vch=#chrs);
if(vch==0, return(str));
for(i=1,vsn,if(!setsearch(vc,vs[i]),v=concat(v,vs[i])));
return(Strchr(v));
};
\\* #4.11 strim() 3/6/16
addhelp(strim, "strim(str,sflag=2): Removes str string whitespace(s) from specifide by sflag side(s) of a string. sflag = 1/2/3 (left, right, both).");
strim(str,sflag=2)={
my(vt=Vecsmall(str),sn=#str,stp=-1,k=-1,ws=32,rs,rsn=0);
if(sn==0, return(""));
if(sflag<1||sflag>3, sflag=2);
if(sflag==2||sflag==3, k=0;
   forstep(i=sn,1,stp, if(vt[i]==ws, k++, break));
   if(k>0, rs=ssubstr(str,,sn-k); rsn=#rs; if(rsn==0,return("")));
   if(k==0, rs=str; rsn=sn);
);
if(k==-1, rs=str; rsn=sn);
if(sflag==1||sflag==3, k=0;
   for(i=1,rsn, if(vt[i]==ws, k++, break));
   if(k>0, rs=ssubstr(rs,k+1,rsn-k));
);
return(rs);
}
   
\\* #4.12 sreplace() 3/8/16
addhelp(sreplace, "sreplace(str,ssrch,srepl): In str string replace all occurrences of the search string ssrch with the replacement string srepl.");
sreplace(str,ssrch,srepl)={
my(sn=#str,ssn=#ssrch,srn=#srepl,sres="",Vi,Vs,Vz,vin,vin1,vi,L=List(),tok,zi,js=1);
if(sn==0,return("")); if(ssn==0||ssn>sn,return(str));
\\ Vi - found ssrch indexes
Vi=sfindalls(str,ssrch); vin=#Vi;
if(vin==0,return(str));
vin1=vin+1; Vi=Vec(Vi,vin1); Vi[vin1]=sn+1;
for(i=1,vin1, vi=Vi[i];
for(j=js,sn, \\print("ij:",i,"/",j,": ",sres);
    if(j!=vi, sres=concat(sres,ssubstr(str,j,1)),
              sres=concat(sres,srepl); js=j+ssn; break) 
   ); \\fend j
); \\fend i
return(sres);
}

\\* #4.14 cleanwsf() 3/10/16
\\* Read the file of strings A.txt (e.g., from OEIS Wiki source containing PARI scripts), clean up it
\\* from Wiki tags, etc., by inserting "\\*" in the beginning of each row starting in the first position,
\\* i.e., if the first position is not a whitespace. Otherwise, and if nw>0, then trim nw first whitespaces.
\\* Write result in the B.txt file.
\\* NOTE: Works only for PARI/GP scripts, and only for my stile of formatting.
addhelp(cleanwsf, "cleanwsf(fpath=\"\"): Using file path fpath and nw as number of whitespaces to trim, - clean up the OEIS Wiki source file A.txt containing PARI scripts. Write result in the B.txt file.");
cleanwsf(fpath="",nw=3)={
my(fin="A.txt",fon="B.txt",fipn=Str(fpath,fin),fopn=Str(fpath,fon),Vin,c="\\\\*",vifn,x,nw1=nw+1);
Vif=readstr(fipn); vifn=#Vif;
for(i=1,vifn, x=sasc(Vif[i]);
    if(x!=32&&x!=-1, Vif[i]=Str(c,Vif[i])); 
    if(x==32, Vif[i]=ssubstr(Vif[i],nw1));
    write(fopn,Vif[i]);
);\\fend i
}

\\* #4.15 clean4gpf() 3/14/16
\\* Read the file of strings B.txt (containing PARI scripts with a lot of comments like \\*), delete all rows
\\* starting with such comments and write result in the C.txt file.
\\* NOTE: Works only for PARI/GP scripts, and only for my stile of formatting.
addhelp(clean4gpf, "clean4gpf(fpath=\"\"): Using file path fpath read the file of strings B.txt, delete all rows starting \\\\*, and write result in the C.txt file.");
clean4gpf(fpath="")={
my(fin="B.txt",fon="C.txt",fipn=Str(fpath,fin),fopn=Str(fpath,fon),Vin,c="\\\\*",vifn,x,nw1=nw+1);
Vif=readstr(fipn); vifn=#Vif;
for(i=1,vifn, x=ssubstr(Vif[i],1,3);
    if(x!=c, write(fopn,Vif[i])); 
);\\fend i
}

\\* ################################   
\\* END OF VoeLib
\\* ################################   
print("*** VoeLib.gp loaded ***"); 
\\currdate(); currtime(); \\ for Windows only!

\\*=== Testing Samples ===
   
/*
{
\\ TESTING SAMPLES FOR VoeLib.gp 
print("*** TESTING ALL FUNCTIONS IN VoeLib.gp ***");
\\ testing factintxt() (Note: your result could be different)
print("***TEST #1 factintxt() RESULT:");
print("*Sample #1*");
\\ Sample #1
for(i=1, 10, j=random(10000); print(j," = ", factintxt(j)));
print("32760 = ",factintxt(32760));
print("*Sample #2*");
\\ Sample #2
Vd=divisors(32760); for(i=1, #Vd, j=Vd[i]; print(i, " ",j," = ", factintxt(j)));
\\ testing findinlist(list, item, {sind})
print("***TEST #2 findinlist() RESULT:");
L1in = List([7,4,5,3,2,1,6,5]); 
print(findinlist(L1in, 5));
print(findinlist(L1in, 5, 1));
print(findinlist(L1in, 5, 4));
print(findinlist(L1in, 9));
print(findinlist(L1in, 9, 2));
L2in = List(["aaa", "bbb", "ccc"]); 
print(findinlist(L2in, "bbb"));
print(findinlist(L2in, "bbb", 3));
L3in = List(); 
print(findinlist(L3in, 3));
\\ testing findinlista(list, item, {sind})
print("***TEST #3 findinlista() RESULT:");
L1in = List([7,4,5,3,2,1,5,6,5]); 
print(findinlista(L1in, 5));
print(findinlista(L1in, 5, 4));
print(findinlista(L1in, 11));
L2in = List(["aaa", "bbb", "ccc", "bbb"]); 
print(findinlista(L2in, "bbb"));
L3in = List(); print(#L3in);
print(findinlista(L3in, 3));
print("***TEST #4 listmax() RESULT:");
Lm=List([4, 2, 1, 8, 27, 0, 64, 9, 2, 125, 65, 8, 8, 2, 9]);
Lm1=List();
Lm2=List([4]);
Lm3=List([-1, -27, -84, -33]);
\\ testing listmax(list, {sind}, {et})
print(listmax(Lm));
print(listmax(Lm,11));
print(listmax(Lm1));
print(listmax(Lm1,1,-777));
print(listmax(Lm2));
print(listmax(Lm3,1,-777));
print(listmax(Lm3,,-777));
\\ testing listmin(list, {sind}, {et})
print("***TEST #5 listmin() RESULT:");
print(listmin(Lm));
print(listmin(Lm,7));
print(listmin(Lm,20,-888));
print(listmin(Lm2));
print(listmin(Lm3,,-888));
print(listmin(Lm3,1,-888));
\\ testing volcomp(v1,v2)
print("***TEST #6 volcomp() RESULT:");
vec1=Vec([5,4,3,9,8,7,3,1]);  vec1=List(vec1);
vec2=Vec([5,4,3,9,8,7,2,1,10,11,11]);
volcomp(vec1,vec2);
\\ testing sortlstgind(list), sortlstbyind(inlist,indlist)
print("***TEST #7-8 sortlstgind()-sortlstbyind() RESULT:");
L1n = List([7,4,5,3,2,1,6]); print("L1N:"); print(L1n); 
Lind = sortlstgind(L1n); print("LIND:"); print(Lind);
L1t = List(["7","4","5","3","2","1","6"]);
L1ts = sortlstbyind(L1t,Lind); print("L1TS:"); print(L1ts);
\\ testing topp10(n)
print("***TEST #9 topp10() RESULT:");
print(topp10(0));
print(topp10(1));
print(topp10(47));
print(topp10(1234));
\\ testing listwui(list)
print("***TEST #10 listwui() RESULT:");
Lm=List([1, 2, 0, 8, 27, 64, 9, 2, 125, 0, 65, 8, 8, 2, 9]); print(Lm);
Lu=listwui(Lm); print(Lu);
\\ testing fmis(mis), gettf(pf=0)
print("***TEST #11-#12 fmis()-gettf() RESULT:");
gettf(1);
\\ testing delfile(fpathname) and renfile(fpathname,fnewname)
print("***TEST #2.1-#2.2 delfile()-renfile() RESULT:");
my(fn1="c:\\Test1.txt",fn2="Test2.txt",fn3="c:\\Test2.txt");
write(fn1,"To be, or not to be?? Hmmm LOL"); 
print("FILE Test1\.txt CREATED");
renfile(fn1,fn2);
print("FILE Test1\.txt RENAMED to Test2\.txt");
delfile(fn3);
print("FILE Test2\.txt DELETED");
\\ testing currdate() and currtime()
print("***TEST #2.3-#2.4 currdate()-currtime() RESULT:");
currdate(); currtime(); 
print("***TEST #3.1-#3.5,#3.9 popmetrics() RESULT:");
a=8; b=8; print(popmetrics(a,b));
a=27; b=216; print(popmetrics(a,b));
a=16; b=17; print(popmetrics(a,b));
a=4; b=127; print(popmetrics(a,b));
a=3; b=125; print(popmetrics(a,b));
a=2; b=6436341; print(popmetrics(a,b));
a=3; b=4; print(popmetrics(a,b));
a=1; b=8; print(popmetrics(a,b));
a=19683; b=157464; print(popmetrics(a,b));
print("*** TESTING STRING FUNCTIONS ***");
print("***TEST #4.1-#4.2 schr()-sasc() RESULT:");
print("1.",sasc(""));
print("2.",sasc(" "));
print("3.",sasc("??error"));
print("4.",schr(63));
print("***TEST #4.3 srepeat() RESULT:");
print("1.",srepeat("a",5));
print("2.",srepeat("ab",5));
print("3.",srepeat("c",1));
print("4.|",srepeat("d",0),"|");
print("5.|",srepeat("",5),"|");
\\print1("6."); for(i=1,10000000, srepeat("e",10));
print("***TEST #4.4 sreverse() RESULT:");
print(sreverse("ABCDEF"));
print("***TEST #4.5 spad() RESULT:");
print("1.",spad("ABCDEF",10,"o"));
print("2.",spad("ABCDEF",12,"."));
print("3.",spad("ABCDEF",12,".",1));
print("4.|",spad("ABCDEF",12),"|");
print("***TEST #4.6 ssubstr() RESULT:");
print(" *** Testing ssubstr():");
print("1.",ssubstr("ABCDEF",2,3));
print("2.",ssubstr("ABCDEF"));
print("3.",ssubstr("ABCDEF",2));
print("4.",ssubstr("ABCDEF",,4));
print("5.",ssubstr("ABCDEF",0,4));
print("6.",ssubstr("ABCDEF",3,7));
print("7.|",ssubstr("",1,4),"|");
print("***TEST #4.7 sfind1s() RESULT:");
print("1.",sfind1s("ABCDEFCDE","CDE"));
print("2.",sfind1s("ABCDEFCDE","CDE",5));
print("3.",sfind1s("AB1DEFCDE","CDE"));
print("4.",sfind1s("ABCDEF","ABCDEF"));
print("5.",sfind1s("ABCDEF","CDF"));
print("6.",sfind1s("ABCDEF","CDE",0));
print("***TEST #4.8 sfindalls() RESULT:");
print("1.",sfindalls("ABCDEF","CDF"));
print("2.",sfindalls("AB","CDE"));
print("3.",sfindalls("ABCDEF","ABCDEF"));
print("4.",sfindalls("ABCDEFCDE","CDE"));
print("5.",sfindalls("AB-ab-AB-AB","AB"));
print("***TEST #4.9 stok() RESULT:");
print("Note: pp - positional parameter(s)");
print("1. 5 pp: ", stok("Hello,How,Are,You,Today",","));
print("2. 5 pp: ", stok("Hello,How,Are,You,Today,",","));
print("2. 9 pp: ", stok(",,Hello,,,How,Are,You,Today",","));
print("4. 6 pp: ", stok(",,,,,,",","));
print("5. 1 pp: ", stok(",",","));
print("6. 1 pp: ", stok("Hello-o-o??",","));
print("7. 0 pp: ", stok("",","));
print("***TEST #4.10 sstripchars() RESULT:");
print("1.",sstripchars("ABCDABCDABCDABCD","AD"));
print("2.",sstripchars("ABCDABCDABCDABCD","BCD"));
print("3.",sstripchars("ABCDABCDABCDABCD","TT"));
print("4.",sstripchars("ABCDABCDABCDABCD",""));
print("***TEST #4.11 strim() RESULT:");
my(s="  abc   ",s1="abc   ",s2="  abc");
print("1.|",strim(s,1),"|");
print("2.|",strim(s),"|");
print("3.|",strim(s,3),"|");
print("4.|",strim(s1,1),"|");
print("5.|",strim(s2,2),"|");
print("***TEST #4.12 sreplace() RESULT:");
my(s="//aa//bbb//cccc//ddddd//",s1="aa//bbb//cccc//ddddd");
print("1. ",sreplace(s,"/","#"));
print("2. ",sreplace(s,"#","@"));
print("3. ",sreplace(s,"//","|"));
print("4. ",sreplace(s,"//","@@@"));
print("5. ",sreplace(s1,"/","%"));
print("***TEST #4.14-#4.15 cleanwsf()-clean4gpf() RESULT:");
    \\Create and save in "c:\pariData\" file A.txt with 15 rows like following
    \\(no "\\" in the beginning):
    \\== Wiki tag1 ==
    \\
    \\=== Wiki tag2 ===
    \\
    \\Just text1
    \\Just text2
    \\
    \\   {\\script1
    \\   \\*script2
    \\   \\*script3
    \\      \\script4
    \\      \\script5
    \\   \\script6}
    \\
    \\== Wiki tag3 ==
cleanwsf("c:\\pariData\\");
clean4gpf("c:\\pariData\\");
}
*/
   
\\*===Results of all tests===

/*
*** RESULTS OF ALL TESTS ***
*** TESTING ALL FUNCTIONS IN VoeLib.gp ***
***TEST #1 factintxt() RESULT:
*Sample #1*
2491 = 47*53
6891 = 3*2297
5007 = 3*1669
5293 = 67*79
4280 = 2^3*5*107
4660 = 2^2*5*233
1032 = 2^3*3*43
3637 = 3637
5712 = 2^4*3*7*17
5357 = 11*487
32760 = 2^3*3^2*5*7*13
*Sample #2*
1 1 = 1
2 2 = 2
3 3 = 3
4 4 = 2^2
5 5 = 5
6 6 = 2*3
7 7 = 7
8 8 = 2^3
9 9 = 3^2
10 10 = 2*5
11 12 = 2^2*3
12 13 = 13
...
93 8190 = 2*3^2*5*7*13
94 10920 = 2^3*3*5*7*13
95 16380 = 2^2*3^2*5*7*13
96 32760 = 2^3*3^2*5*7*13
***TEST #2 findinlist() RESULT:
3
3
8
0
0
2
0
0
***TEST #3 findinlista() RESULT:
List([3, 7, 9])
List([7, 9])
List([])
List([2, 4])
0
List([])
***TEST #4 listmax() RESULT:
125
65
-1
-777
4
-1
-1
***TEST #5 listmin() RESULT:
0
2
-888
4
-84
-84
***TEST #6 volcomp() RESULT:
 *** COMPARE v1&v2 w/types: t_LIST/t_VEC; w/sizes: 8/11
 *** can compare only first 8 elements.
 *** v1 and v2 are NOT identical at v1[7]!?
***TEST #7-8 sortlstgind()-sortlstbyind() RESULT:
L1N:
List([7, 4, 5, 3, 2, 1, 6])
LIND:
List([6, 5, 4, 2, 3, 7, 1])
L1TS:
List(["1", "2", "3", "4", "5", "6", "7"])
***TEST #9 topp10() RESULT:
0
10
100
10000
***TEST #10 listwui() RESULT:
List([1, 2, 0, 8, 27, 64, 9, 2, 125, 0, 65, 8, 8, 2, 9])
List([1000, 2001, 1, 8001, 27000, 64000, 9001, 2002, 125000, 2, 65000, 8002, 800
3, 2003, 9002])
***TEST #11-#12 fmis()-gettf() RESULT:
0min 9sec 234ms
***TEST #2.1-#2.2 delfile()-renfile() RESULT:
FILE Test1.txt CREATED
FILE Test1.txt RENAMED to Test2.txt
FILE Test2.txt DELETED
***TEST #2.3-#2.4 currdate()-currtime() RESULT:
Tue 11/24/2015
01:22 PM
***TEST #3.1-#3.5,#3.9 popmetrics() RESULT:
*8*|sz2|r2|mr-2.29|q4.0000
*27*|sz3|r6|mr4.46|q3.0657
*1*|sz2|r1122|mr3.45|q0.4979
*1*|sz3|r33274|mr6.90|q0.4682
*1*|sz3|r30|mr0.76|q1.4266
*1*|sz7|r15042|mr8.64|q1.6299
*1*|sz1|r42|mr1.13|q0.5206
*1*|sz1|r6|mr0.05|q1.2263
*19683*|sz6|r6|mr34.48|q6.7446
*** TESTING STRING FUNCTIONS ***
***TEST #4.1-#4.2 schr()-sasc() RESULT:
1.-1
2.32
3.63
4.?
***TEST #4.3 srepeat() RESULT:
1.aaaaa
2.ababababab
3.c
4.||
5.||
***TEST #4.4 sreverse() RESULT:
FEDCBA
***TEST #4.5 spad() RESULT:
1.ABCDEFoooo
2.ABCDEF......
3.......ABCDEF
4.|ABCDEF      |
***TEST #4.6 ssubstr() RESULT:
 *** Testing ssubstr():
1.BCD
2.ABCDEF
3.BCDEF
4.ABCD
5.ABCDEF
6.CDEF
7.||
***TEST #4.7 sfind1s() RESULT:
1.3
2.7
3.7
4.1
5.0
6.0
***TEST #4.8 sfindalls() RESULT:
1.[]
2.[]
3.[1]
4.[3, 7]
5.[1, 7, 10]
***TEST #4.9 stok() RESULT:
Note: pp - positional parameter(s)
1. 5 pp: ["Hello", "How", "Are", "You", "Today"]
2. 5 pp: ["Hello", "How", "Are", "You", "Today"]
2. 9 pp: ["", "", "Hello", "", "", "How", "Are", "You", "Today"]
4. 6 pp: ["", "", "", "", "", ""]
5. 1 pp: [""]
6. 1 pp: ["Hello-o-o??"]
7. 0 pp: [""]
***TEST #4.10 sstripchars() RESULT:
1.BCBCBCBC
2.AAAA
3.ABCDABCDABCDABCD
4.ABCDABCDABCDABCD
***TEST #4.11 strim() RESULT:
1.|abc   |
2.|  abc|
3.|abc|
4.|abc   |
5.|  abc|
***TEST #4.12 sreplace() RESULT:
1. ##aa##bbb##cccc##ddddd##
2. //aa//bbb//cccc//ddddd//
3. |aa|bbb|cccc|ddddd|
4. @@@aa@@@bbb@@@cccc@@@ddddd@@@
5. aa%%bbb%%cccc%%ddddd
***TEST #4.14-#4.15 cleanwsf()-clean4gpf() RESULT:
   \\ check/review files B.txt and C.txt in c:\pariData\
   
     NOTE: 1. Clean-up rules: delete all rows starting at position 1.
           2. You may add "\\" in front of them instead of deleting.
           3. You can cut tales called "TESTING SAMPLES FOR VoeLib.gp" together
              with "RESULTS OF ALL TESTS" plus rest of this file and save it in
              a different file.
*/
   
\\*== Significant Testing Sample ==

\\*This sample script, producing presentation file for the sequence A264901, would not be possible
\\*without small, but powerful library VoeLib.gp. Installed original PARI/GP library simply has no appropriate
\\*functions.

\\*Note: first 2 columns of a264901 file are actually b264901 file. But generating b-file is much easier. (See my script for b-file.) Only 1 function from VoeLib.gp was used.

\\*If you already tested all VoeLib.gp functions using my samples, now, you can really see why 
\\*they were created and how they perform.

\\*I'm sure you will use many of them for presentation and testing right away.
   
   /*
   a264901(lim)=
   {my(Lc=List(1),Lct=List("1^3"),Lb=List(),La=Lb,Lc1=Lb,Lcu=Lb,Lci=Lb,L3=Lb,
       czn,lcn,l3n,lan,ki,lim2=logint(lim, 2),lim3,l3t,lct,g,fg);
      for(z=3, lim2, lim3=sqrtnint(lim, z);
          for(C=2, lim3, listput(Lc, C^z); lct=concat([C,"^",z]); listput(Lct,lct) ));
      lcn = #Lc; if(lcn==0, print(" *** ERROR: WRONG LC/LCT size!"); return(-1));
      for(i=1, lcn,  
      for(j=i, lcn, czn=Lc[i]+Lc[j]; if(czn>lim, next);
          La=findinlista(Lc, czn); lan=#La; if(!lan, next);
          for(k=1,lan, listput(Lc1, czn); ki=La[k];
              g=gcd(Lc[i],Lc[j]); fg=factintxt(g); if(g==1,fg=concat([fg,"###"]));
              l3t = concat([czn," = ", Lc[i]," + ",Lc[j]," ==> ", Lct[ki]," = ",Lct[i]," + ",Lct[j],
                            " ==> ",factintxt(czn)," = ",factintxt(Lc[i])," + ",factintxt(Lc[j]),
                            " ==> ",fg]);
              listput(L3, l3t);)
      ));
      l3n = #L3;
      kill(Lc); kill(Lct); kill(La);
      Lcu=listwui(Lc1); Lci = sortlstgind(Lcu);
      kill(Lcu); kill(Lc1);
      Lb = sortlstbyind(L3,Lci);
      kill(Lci); kill(L3);
      for(i=1, l3n, print(i," ",Lb[i]));
      }

   
   \\ *** Testing 
   a264901(10000);
   */
   
\\*=== Results of testing ===

\\*The following a264901 file expands b264901 with 4 parts separated with "==>" sign.<br />
\\*First 3 parts have Beal's type of equation, i.e., C^z = A^x + B^y
\\*in the following 3 forms:
\\**1. In numbers.
\\**2. In powers (for those who are curious if there is a counterexample to FLT).
\\**3. In factors (for those who are curious if there is a counterexample to Beal's conjecture).
\\*Last 4th part has gcd(A^x,B^y). Can you find gcd=1? If not, Beal's
\\*conjecture is OK so far... (Hint: gcd=1 would be marked with "###".)

 
  /* 
    (21:13) gp > a264901(10000)
   1 16 = 8 + 8 ==> 2^4 = 2^3 + 2^3 ==> 2^4 = 2^3 + 2^3 ==> 2^3
   2 32 = 16 + 16 ==> 2^5 = 2^4 + 2^4 ==> 2^5 = 2^4 + 2^4 ==> 2^4
   3 64 = 32 + 32 ==> 4^3 = 2^5 + 2^5 ==> 2^6 = 2^5 + 2^5 ==> 2^5
   4 64 = 32 + 32 ==> 2^6 = 2^5 + 2^5 ==> 2^6 = 2^5 + 2^5 ==> 2^5
   5 128 = 64 + 64 ==> 2^7 = 4^3 + 4^3 ==> 2^7 = 2^6 + 2^6 ==> 2^6
   6 128 = 64 + 64 ==> 2^7 = 4^3 + 2^6 ==> 2^7 = 2^6 + 2^6 ==> 2^6
   7 128 = 64 + 64 ==> 2^7 = 2^6 + 2^6 ==> 2^7 = 2^6 + 2^6 ==> 2^6
   8 243 = 27 + 216 ==> 3^5 = 3^3 + 6^3 ==> 3^5 = 3^3 + 2^3*3^3 ==> 3^3
   9 256 = 128 + 128 ==> 4^4 = 2^7 + 2^7 ==> 2^8 = 2^7 + 2^7 ==> 2^7
   10 256 = 128 + 128 ==> 2^8 = 2^7 + 2^7 ==> 2^8 = 2^7 + 2^7 ==> 2^7
   11 512 = 256 + 256 ==> 8^3 = 4^4 + 4^4 ==> 2^9 = 2^8 + 2^8 ==> 2^8
   12 512 = 256 + 256 ==> 2^9 = 4^4 + 4^4 ==> 2^9 = 2^8 + 2^8 ==> 2^8
   13 512 = 256 + 256 ==> 8^3 = 4^4 + 2^8 ==> 2^9 = 2^8 + 2^8 ==> 2^8
   14 512 = 256 + 256 ==> 2^9 = 4^4 + 2^8 ==> 2^9 = 2^8 + 2^8 ==> 2^8
   15 512 = 256 + 256 ==> 8^3 = 2^8 + 2^8 ==> 2^9 = 2^8 + 2^8 ==> 2^8
   16 512 = 256 + 256 ==> 2^9 = 2^8 + 2^8 ==> 2^9 = 2^8 + 2^8 ==> 2^8
   17 1024 = 512 + 512 ==> 4^5 = 8^3 + 8^3 ==> 2^10 = 2^9 + 2^9 ==> 2^9
   18 1024 = 512 + 512 ==> 2^10 = 8^3 + 8^3 ==> 2^10 = 2^9 + 2^9 ==> 2^9
   19 1024 = 512 + 512 ==> 4^5 = 8^3 + 2^9 ==> 2^10 = 2^9 + 2^9 ==> 2^9
   20 1024 = 512 + 512 ==> 2^10 = 8^3 + 2^9 ==> 2^10 = 2^9 + 2^9 ==> 2^9
   21 1024 = 512 + 512 ==> 4^5 = 2^9 + 2^9 ==> 2^10 = 2^9 + 2^9 ==> 2^9
   22 1024 = 512 + 512 ==> 2^10 = 2^9 + 2^9 ==> 2^10 = 2^9 + 2^9 ==> 2^9
   23 2048 = 1024 + 1024 ==> 2^11 = 4^5 + 4^5 ==> 2^11 = 2^10 + 2^10 ==> 2^10
   24 2048 = 1024 + 1024 ==> 2^11 = 4^5 + 2^10 ==> 2^11 = 2^10 + 2^10 ==> 2^10
   25 2048 = 1024 + 1024 ==> 2^11 = 2^10 + 2^10 ==> 2^11 = 2^10 + 2^10 ==> 2^10
   26 2744 = 343 + 2401 ==> 14^3 = 7^3 + 7^4 ==> 2^3*7^3 = 7^3 + 7^4 ==> 7^3
   27 4096 = 2048 + 2048 ==> 16^3 = 2^11 + 2^11 ==> 2^12 = 2^11 + 2^11 ==> 2^11
   28 4096 = 2048 + 2048 ==> 8^4 = 2^11 + 2^11 ==> 2^12 = 2^11 + 2^11 ==> 2^11
   29 4096 = 2048 + 2048 ==> 4^6 = 2^11 + 2^11 ==> 2^12 = 2^11 + 2^11 ==> 2^11
   30 4096 = 2048 + 2048 ==> 2^12 = 2^11 + 2^11 ==> 2^12 = 2^11 + 2^11 ==> 2^11
   31 6561 = 729 + 5832 ==> 9^4 = 9^3 + 18^3 ==> 3^8 = 3^6 + 2^3*3^6 ==> 3^6
   32 6561 = 729 + 5832 ==> 3^8 = 9^3 + 18^3 ==> 3^8 = 3^6 + 2^3*3^6 ==> 3^6
   33 6561 = 5832 + 729 ==> 9^4 = 18^3 + 3^6 ==> 3^8 = 2^3*3^6 + 3^6 ==> 3^6
   34 6561 = 5832 + 729 ==> 3^8 = 18^3 + 3^6 ==> 3^8 = 2^3*3^6 + 3^6 ==> 3^6
   35 8192 = 4096 + 4096 ==> 2^13 = 16^3 + 16^3 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   36 8192 = 4096 + 4096 ==> 2^13 = 16^3 + 8^4 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   37 8192 = 4096 + 4096 ==> 2^13 = 16^3 + 4^6 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   38 8192 = 4096 + 4096 ==> 2^13 = 16^3 + 2^12 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   39 8192 = 4096 + 4096 ==> 2^13 = 8^4 + 8^4 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   40 8192 = 4096 + 4096 ==> 2^13 = 8^4 + 4^6 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   41 8192 = 4096 + 4096 ==> 2^13 = 8^4 + 2^12 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   42 8192 = 4096 + 4096 ==> 2^13 = 4^6 + 4^6 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   43 8192 = 4096 + 4096 ==> 2^13 = 4^6 + 2^12 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   44 8192 = 4096 + 4096 ==> 2^13 = 2^12 + 2^12 ==> 2^13 = 2^12 + 2^12 ==> 2^12
   (21:15) gp > ##
     ***   last result computed in 62 ms.
  
   */
